#include "MeshView.hpp"
#include "gl.hpp"
#include "ViewScene.hpp"
#include "MeshAlgorithm.hpp"
#include "SubdivisionAlgorithm.hpp"
#include "DebugHelper.hpp"
#include "MeshAdjacency.hpp"
#include "SelectTexture.hpp"

MeshView::MeshView(bool aIsSubdivMesh)
: mPolyView(mMesh.verts, mMesh.polys),
   mAdjacency(mMesh.GetCreaseMesh())
{
   mMeshAdjacencyValid = false;
   mCreasesUpdated = false;
   mOptions = cKEEP_CREASE_STRUCTURE;
   mFaceUpdating = true;
   mPolyUpdating = true;
   mVisible = true;
   mSubdivisionLevel = 0;
   mSubdividedMesh = 0;
   if (! aIsSubdivMesh)
   {
      CreateSubdivisionMesh();
   }
}

MeshView::~MeshView()
{
   delete mSubdividedMesh;
}

void MeshView::CreateSubdivisionMesh()
{
   mSubdividedMesh = new MeshView(true);
   mConfig.mOutlineFaces = true;
   mConfig.mShowFaces = mConfig.mShowPolys = mConfig.mOutlinePolys = false;
   CopyConfigPart(mSubdividedMesh->mConfig, mConfig);
}

void MeshView::Draw()
{
   if (! mVisible) return;
   if (mSubdividedMesh) mSubdividedMesh->Draw();

   if (mFaceUpdating && (mConfig.mShowFaces || mConfig.mOutlineFaces))
   {
      UpdateFaceMesh();
   }

   if (mConfig.mShowPolys)
   {
      DrawPolys();
   }
   else if (mConfig.mOutlinePolys)
   {
      gl::NoDepthTest state;
      glColor3f(0,0,0);
      DrawWireframe(mPolyMeshDraw);
   }

   if (mConfig.mShowFaces)
   {
      DrawFaces();
   }
   else if (mConfig.mOutlineFaces)
   {
      gl::NoDepthTest state;
      glColor3f(0,0,0);
      if (mSubdividedMesh != 0)
      {
         glColor3f(.5,.5,.5);
      }
      DrawWireframe(mFaceMeshDraw);
   }
   
   if (mConfig.mShowVerts)
   {
      DrawAllVerts();
   }

   if (mConfig.mShowCreaseEdges)
   {
      DrawEdges();
   }
   
   if (ViewScene::GetInstance().GetSelectionMode() == ViewScene::cVERTEX)
   {
      DrawSelVertices();
   }
   else if (ViewScene::GetInstance().GetSelectionMode() == ViewScene::cLOOP)
   {
      DrawSelLoops();
   }
   else if (ViewScene::GetInstance().GetSelectionMode() == ViewScene::cINTERFACE)
   {
      DrawSelFaces();
   }
   else if (ViewScene::GetInstance().GetSelectionMode() == ViewScene::cFACE)
   {
      DrawSelFaces();
      DrawSelVertices();
   }
   else if (ViewScene::GetInstance().GetSelectionMode() == ViewScene::cEDGE_PATCH)
   {
      DrawSelEdges();
   }
   DrawLandmarks();
}

void MeshView::UpdateSharedConfig(MeshViewConfig& aConfig)
{
   // Shared config data...
   bool regionChange = aConfig.mHiddenRegions != mConfig.mHiddenRegions;
   mConfig.mHiddenRegions = aConfig.mHiddenRegions;
   if (mConfig.mFlipMaterials != aConfig.mFlipMaterials)
   {
      mConfig.mFlipMaterials = aConfig.mFlipMaterials;
      mFaceUpdating = true;
   }
   if (regionChange)
   {
      mPolyUpdating = mFaceUpdating = true;
   }
}

void MeshView::SetConfig(MeshViewConfig& aConfig,
                         bool            aSubdivConfig)
{
   UpdateSharedConfig(aConfig);
   
   if (aSubdivConfig) // Pass to subdivision mesh...
   {
      if (mSubdividedMesh != 0)
      {
         mSubdividedMesh->SetConfig(aConfig, false);
      }
      return;
   }
   else if (mSubdividedMesh != 0)
   {
      mSubdividedMesh->UpdateSharedConfig(aConfig);
   }

   // Local config options...
   bool rebuildPolyMesh(false);
   mFaceUpdating = mFaceUpdating;
   if ((aConfig.mShowPolys || aConfig.mOutlinePolys) && aConfig.mPolyScale != mConfig.mPolyScale)
   {
      mPolyView.SetPolyScaling(aConfig.mPolyScale);
      rebuildPolyMesh = true;
   }
   rebuildPolyMesh = rebuildPolyMesh || mConfig.mShowPolys != aConfig.mShowPolys;
   mPolyUpdating = mPolyUpdating || rebuildPolyMesh;
   mConfig = aConfig;
   mShownVertices.clear();
}

void MeshView::UpdateFaceMesh()
{
   using namespace MeshAlgorithm;
   
   mFaceMesh.faces.clone(mMesh.crease_faces);
   mFaceMesh.verts.ref(mMesh.verts);
   RemoveHiddenMaterials(mFaceMesh);
   if (mConfig.mFlipMaterials)
   {
      MeshAlgorithm::FlipMaterials(mFaceMesh);
   }
   mFaceMeshDraw.SetMesh(mFaceMesh);
   mFaceUpdating = false;
}

void MeshView::RemoveHiddenMaterials(Mesh& aMesh)
{
   using namespace MeshAlgorithm;
   std::vector<int> regions;
   GetShownRegions(regions);
   if (! mConfig.mHiddenRegions.empty())
   {
      SelectMaterials mats(regions.begin(), regions.end());
      RemoveFacesKeepVerts(mFaceMesh, Inverse(mats));
   }
}

void MeshView::UpdatePolyMesh()
{
   mPolyUpdating = false;
   std::vector<int> regions;
   GetShownRegions(regions);
   mPolyView.SetShownMaterialList(regions);
   mPolyView.UseMaterialList(! mConfig.mHiddenRegions.empty());
   mPolyView.BuildMesh();
   mPolyMeshDraw.SetMesh(mPolyView.GetMesh());
}

void MeshView::UpdateMesh()
{
   if (mSubdividedMesh != 0)
   {
      if (GetSubdivision() == 0)
      {
         mSubdividedMesh->mMesh.ref(mMesh);
         mSubdividedMesh->mPolyView.Reset(mSubdividedMesh->mMesh.verts, mSubdividedMesh->mMesh.polys);
         mSubdividedMesh->mPolyMeshDraw.SetMesh(mSubdividedMesh->mPolyView.GetMesh());
      }
      else
      {
         mSubdividedMesh->mMesh.clone(mMesh);
         mSubdividedMesh->mPolyView.Reset(mSubdividedMesh->mMesh.verts, mSubdividedMesh->mMesh.polys);
         mSubdividedMesh->mPolyMeshDraw.SetMesh(mSubdividedMesh->mPolyView.GetMesh());
      }
      mSubdividedMesh->UpdateMesh();
   }
   mPolyUpdating = mFaceUpdating = true;   
   mMeshAdjacencyValid = false;
   mShownVertices.clear();
   UpdateRegions();
   if (mSubdividedMesh != 0)  // only build crease structure for base mesh
   {
      mCreasesUpdated = false;
   }
}
//
//void MeshView::DrawEdges()
//{
//   ViewScene::GetInstance().LoadProjection(1/1.001f);
//   gl::NoLighting state2;
//   glColor3f(1,0,0);
//   glLineWidth(2.0);
//   glBegin(GL_LINES);
//   EdgeList& edges = *mMesh.crease_edges;
//   
//   size_t edgeCount = edges.size();
//   for (size_t i = 0; i < edgeCount; ++i)
//   {
//      const Edge& e = edges[i];
//      gl::Vertex(mMesh.verts[e.first]);
//      gl::Vertex(mMesh.verts[e.second]);
//   }
//   glEnd();
//   glLineWidth(1.0);
//   ViewScene::GetInstance().LoadProjection(1.0);
//}

void MeshView::DrawEdges()
{
   //gl::NoDepthTest statendt;
   ViewScene::GetInstance().LoadProjection(1/1.001f);
   gl::NoLighting state2;
   glColor3f(1,0,0);
   glLineWidth(2.0);
   //glEnable(GL_LINE_STIPPLE);
   //glLineStipple(1, 0x5555);
   if (mSubdividedMesh != 0)
   {
      CreaseStructure& creases = GetCreases();
      for (size_t i = 0; i < creases.mPatches.size(); ++i)
      {
         RegionCrease& crease = *creases.mPatches[i];
         RegionInterface region = crease.mInterface;
         if ((region.first == -1 || (std::find(mConfig.mHiddenRegions.begin(), mConfig.mHiddenRegions.end(), region.first)
            != mConfig.mHiddenRegions.end()))
            && (region.second == -1 || (std::find(mConfig.mHiddenRegions.begin(), mConfig.mHiddenRegions.end(), region.second)
            != mConfig.mHiddenRegions.end()))
            )
         {
            continue;
         }
         glBegin(GL_LINES);
         for (size_t j = 0; j < crease.mLoops.size(); ++j)
         {
            VertexLoop& loop = *crease.mLoops[j];
            for (int j = 1; j < loop.mVertices.size(); ++j)
            {
               gl::Vertex(mMesh.verts[loop.mVertices[j]]);
               gl::Vertex(mMesh.verts[loop.mVertices[j-1]]);
            }
            gl::Vertex(mMesh.verts[loop.mVertices.front()]);
            gl::Vertex(mMesh.verts[loop.mVertices.back()]);
         }
         glEnd();
      }
      
   }
   else
   {
      ViewScene::GetInstance().LoadProjection(1/1.01f);
      glEnable(GL_LINE_STIPPLE);
      glLineStipple(2, 0xAAAA);
      glColor3f(0,1,1);
      glLineWidth(2.0f);
      glBegin(GL_LINES);
      EdgeList& edges = *mMesh.crease_edges;

      size_t edgeCount = edges.size();
      for (size_t i = 0; i < edgeCount; ++i)
      {
         const Edge& e = edges[i];
         gl::Vertex(mMesh.verts[e.first]);
         gl::Vertex(mMesh.verts[e.second]);
      }
      glEnd();
      glDisable(GL_LINE_STIPPLE);
   }
   glLineWidth(1.0f);
   ViewScene::GetInstance().LoadProjection(1.0);
}

void MeshView::DrawFaces()
{
   if (mConfig.mFaceAlpha >= 1.0)
   {
      mFaceMeshDraw.Draw();
   }
   else 
   {
      gl::Blend state0;
      gl::NoDepthTest state1;
      mFaceMeshDraw.Draw(mConfig.mFaceAlpha);
   }
   
   if (mConfig.mOutlineFaces)
   {
      glColor3f(0,0,0);
      glDepthFunc(GL_LESS);
      ViewScene::GetInstance().LoadProjection(1/1.005f);
      DrawWireframe(mFaceMeshDraw);
      ViewScene::GetInstance().LoadProjection(1.0f);
      glDepthFunc(GL_LEQUAL);
   }
}

void MeshView::DrawSelVertices()
{
   VertexList& verts = *mMesh.verts;
   glEnable(GL_POINT_SMOOTH);
   gl::NoDepthTest format1;
   gl::NoLighting  format2;

   glPointSize(4.0);
   glColor3f(1,1,1);
   glBegin(GL_POINTS);
   for (size_t i = 0; i < mSelectedVerts.size(); ++i)
   {
      const Vec3& vec = verts[mSelectedVerts[i]];
      gl::Vertex(vec);
   }
   glEnd();

   glPointSize(1.5);
   glColor3f(0,0,0);

   glBegin(GL_POINTS);
   for (size_t i = 0; i < mSelectedVerts.size(); ++i)
   {
      const Vec3& vec = verts[mSelectedVerts[i]];
      gl::Vertex(vec);
   }
   glEnd();
}

void MeshView::DrawSelLoops()
{
   if (mSubdividedMesh == 0) return;
   if (mSelectedLoops.empty()) return;
   ViewScene::GetInstance().LoadProjection(1/1.001f);
   gl::NoLighting state2;
   glColor3f(1,0,0);
   glLineWidth(5.0);
   glEnable(GL_LINE_STIPPLE);
   glLineStipple(2, 0xAAAA);
   CreaseStructure& creases = GetCreases();
   for (int times = 0; times < 2; ++times)
   {
      if (times == 1) 
      {
         glColor3f(0,1,1);
         glLineStipple(2, ~0xAAAA);
      }
      for (size_t i = 0; i < mSelectedLoops.size(); ++i)
      {
         int loopInd = mSelectedLoops[i];
         if (creases.mLoops.size() > loopInd)
         {
            VertexLoop& loop = *creases.mLoops[loopInd];
            glBegin(GL_LINES);
               for (size_t j = 1; j < loop.mVertices.size(); ++j)
               {
                  gl::Vertex(mMesh.verts[loop.mVertices[j]]);
                  gl::Vertex(mMesh.verts[loop.mVertices[j-1]]);
               }
               gl::Vertex(mMesh.verts[loop.mVertices.front()]);
               gl::Vertex(mMesh.verts[loop.mVertices.back()]);
            glEnd();
         }
      }
   }
   glDisable(GL_LINE_STIPPLE);

   glLineWidth(1.0f);
   ViewScene::GetInstance().LoadProjection(1.0);
}

void MeshView::DrawPolys()
{
   if (mPolyUpdating)
   {
      UpdatePolyMesh();
   }
   if (mConfig.mPolyAlpha >= 1.0)
   {
      mPolyMeshDraw.Draw();
   }
   else 
   {
      gl::Blend state0;
      gl::NoDepthTest state1;
      mPolyMeshDraw.Draw(mConfig.mPolyAlpha);
   }

   if (mConfig.mOutlinePolys)
   {
      glColor3f(0,0,0);
      glDepthFunc(GL_LESS);
      ViewScene::GetInstance().LoadProjection(1/1.0005f);
      DrawWireframe(mPolyMeshDraw);
      ViewScene::GetInstance().LoadProjection(1.0f);
      glDepthFunc(GL_LEQUAL);
   }
}
void MeshView::DrawLandmarks()
{
   if (! mConfig.mShowLandmarks) return;
   glEnable(GL_POINT_SMOOTH);
   gl::NoLighting state1;
   glPointSize(3);
   glColor3f(1,1,0);
   ViewScene::GetInstance().LoadProjection(1/1.0005f);
   std::vector<int> shownRegions;
   GetShownRegions(shownRegions);
   std::vector<char> isShown(32, false);
   for (int i = 0; i < shownRegions.size(); ++i)
   {
      isShown[shownRegions[i]+1]=true;
   }
   char* isRegionShown = &isShown[1];
   glBegin(GL_POINTS);
   for (size_t i = 0; i < mLandmarks.size(); ++i)
   {
      bool show=false;
      MatPoint& lm = mLandmarks[i];
      for (int j = 0; j < lm.materials.size(); ++j)
      {
         show|=isRegionShown[lm.materials[j]];
      }
      if (show)
      {
         gl::Vertex(lm.point);
      }
   }
   glEnd();
   ViewScene::GetInstance().LoadProjection(1);  
}
void MeshView::DrawWireframe(MeshDraw& aMeshDraw)
{
   gl::NoLighting state;
   glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
   aMeshDraw.EnableMaterials(false);
   aMeshDraw.Draw();
   aMeshDraw.EnableMaterials(true);
   glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}

void MeshView::UpdateRegions()
{
   DEBUG_LOG("UpdateRegions");
   bool neg1=false;
   int matMask = 0;
   PolyhedronList& polys = *mMesh.polys;
   for (size_t i = 0; i < polys.size(); ++i)
   {
      int mat = polys[i].material;
      if (mat >= 0)
      {
         matMask |= 1<<mat;
      }
   }

   if (polys.empty())
   {
      for (size_t i = 0; i < mMesh.crease_faces.size(); ++i)
      {
         Face& f = mMesh.crease_faces[i];
         int mat = f.materials[0];
         if (mat >= 0)
         {
            matMask |= 1<<mat;
         }
         else
         {
            neg1=true;
         }
         mat = f.materials[1];
         if (mat >= 0)
         {
            matMask |= 1<<mat;
         }
         else
         {
            neg1=true;
         }
      }
   }
   mRegions.clear();
   if (neg1) mRegions.push_back(-1);
   for (int i = 0; i < 31; ++i)
   {
      if (matMask & (1<<i))
      {
         mRegions.push_back(i);
      }
   }
   if (neg1)
   {
      if (std::find(mConfig.mHiddenRegions.begin(), mConfig.mHiddenRegions.end(), -1) ==mConfig.mHiddenRegions.end())
         mConfig.mHiddenRegions.push_back(-1);
   }
   DEBUG_LOG(".\n");
}
void MeshView::GetShownRegions(std::vector<int>& aRegions)
{
   aRegions = mRegions;
   for (size_t i = 0; i < mConfig.mHiddenRegions.size(); ++i)
   {
      int r = mConfig.mHiddenRegions[i];
      std::vector<int>::iterator iter = std::find(aRegions.begin(), aRegions.end(), r);
      if (iter != aRegions.end())
      {
         aRegions.erase(iter);
      }
   }
}

void MeshView::SetSubdivision(int aLevel)
{
   if (mSubdivisionLevel != aLevel)
   {
      mSubdivisionLevel = aLevel;
      if (mSubdividedMesh)
      {
         if (mSubdivisionLevel != 0)
         {
            mSubdividedMesh->mMesh.clone(mMesh);
            mSubdividedMesh->mPolyView.Reset(mSubdividedMesh->mMesh.verts, mSubdividedMesh->mMesh.polys);
            mSubdividedMesh->mPolyMeshDraw.SetMesh(mSubdividedMesh->mPolyView.GetMesh());
            if (mSubdivisionLevel > 0)
            {
               SubdivisionAlgorithm::SubdivideMesh(mSubdividedMesh->mMesh, mSubdivisionLevel);
            }
         }
         else
         {
            mSubdividedMesh->mMesh.ref(mMesh);
            mSubdividedMesh->mPolyView.Reset(mMesh.verts, mMesh.polys);
            mSubdividedMesh->mPolyMeshDraw.SetMesh(mSubdividedMesh->mPolyView.GetMesh());
         }
         mSubdividedMesh->UpdateMesh();
      }
   }
}
void MeshView::DrawCentroid()
{

}
void MeshView::DrawAllVerts()
{
   if (mShownVertices.empty())
   {
      std::vector<int> regions;
      GetShownRegions(regions);
      if (regions.empty()) return;
      std::set<int> rs(regions.begin(), regions.end());
      const FaceList& faces = *mMesh.crease_faces;
      for (size_t i = 0; i < faces.size(); ++i)
      {
         const Face& f = faces[i];
         if (rs.find(f.materials[0]) != rs.end()
            || rs.find(f.materials[1]) != rs.end())
         {
            mShownVertices.insert(mShownVertices.end(), f.vertex.begin(), f.vertex.end());
         }
      }
      std::sort(mShownVertices.begin(), mShownVertices.end());
      mShownVertices.erase(std::unique(mShownVertices.begin(), mShownVertices.end()), mShownVertices.end());
   }
   const std::vector<Vec3>& verts = *mMesh.verts;
   
   glEnable(GL_POINT_SMOOTH);
   gl::NoLighting state1;
   {
      ViewScene::GetInstance().LoadProjection(1/1.0005f);
      glColor3f(1,0,1);
      glPointSize(3);
      glBegin(GL_POINTS);
      for (size_t i = 0; i < mShownVertices.size(); ++i)
      {
         gl::Vertex(verts[mShownVertices[i]]);
      }
      glEnd();
   }
   glDisable(GL_POINT_SMOOTH);
   {
      ViewScene::GetInstance().LoadProjection(1/1.001f);
      glColor3f(1,1,0);
      gl::NoDepthTest state2;
      glPointSize(1);
      glBegin(GL_POINTS);
      for (size_t i = 0; i < mShownVertices.size(); ++i)
      {
         gl::Vertex(verts[mShownVertices[i]]);
      }
      glEnd();
   }
   ViewScene::GetInstance().LoadProjection(1.0f);
   glDisable(GL_POINT_SMOOTH);
}
void MeshView::SelectAllVertices()
{
   mSelectedVerts.assign(boost::counting_iterator<int>(0), boost::counting_iterator<int>(mMesh.verts.size()));
   SelectionUpdated();
}

void MeshView::SelectionUpdated()
{
   //if (ViewScene::GetInstance().GetSelectionMode() == ViewScene::cVERTEX)
   //{
   //   mCentroid.set(0,0,0);
   //   size_t vertCount = mMesh.verts.size();
   //   for (size_t i = 0; i < mSelectedVerts.size(); ++i)
   //   {
   //      int v = mSelectedVerts[i];
   //      if (v < vertCount)
   //      {
   //         mCentroid += mMesh.verts[v];
   //      }
   //   }
   //   mCentroid /= mSelectedVerts.size();
   //   ViewScene::SelectedVertsChanged();
   //}
   //else if (ViewScene::GetInstance().GetSelectionMode() == ViewScene::cINTERFACE)
   //{
   //   mCentroid.set(0,0,0);
   //   if (mCreases.mPatches.size() > mSelectedInterface && mSelectedInterface >= 0)
   //   {
   //      int addCt = 0;
   //      RegionCrease* crease = mCreases.mPatches[mSelectedInterface];
   //      for (size_t i = 0; i < crease->mFaces.size(); ++i)
   //      {
   //         size_t fi = crease->mFaces[i];
   //         Face& f = mMesh.crease_faces[fi];
   //         ++addCt;
   //         mCentroid += mMesh.verts[f.vertex[0]];
   //      }
   //      mCentroid /= addCt;
   //   }
   //}
   //else if (ViewScene::GetInstance().GetSelectionMode() == ViewScene::cFACE)
   //{
   //   ViewScene::SelectedVertsChanged();
   //}
   if (ViewScene::GetInstance().GetSelectionMode() == ViewScene::cVERTEX)
   {
      MeshAlgorithm::FindFaces(*mMesh.crease_faces, GetSelectedVertices(), mSelectedFaces);
   }
   if (ViewScene::GetInstance().GetSelectionMode() == ViewScene::cFACE)
   {
      mSelectedVerts.clear();
      for (size_t i = 0; i < mSelectedFaces.size(); ++i)
      {
         int fi = mSelectedFaces[i];
         Face& f= mMesh.crease_faces[fi];
         for (int j = 0; j < 3; ++j) mSelectedVerts.push_back(f.vertex[j]);
      }
      std::sort(mSelectedVerts.begin(), mSelectedVerts.end());
      mSelectedVerts.erase(std::unique(mSelectedVerts.begin(), mSelectedVerts.end()), mSelectedVerts.end());
   }
   ViewScene::SelectedVertsChanged();
}
//
//void MeshView::DrawSelInterface()
//{
//   if (mSelectedInterface < 0) return;
//   CreaseStructure& creases = GetCreases();
//   if (creases.mPatches.size() <= mSelectedInterface) return;
//   RegionCrease* crease = creases.mPatches[mSelectedInterface];
//   gl::NoLighting state1;
//   {
//      gl::Blend state2;
//      ViewScene::GetInstance().LoadProjection(1/1.0005f);
//      glDisable(GL_CULL_FACE);
//      glBegin(GL_TRIANGLES);
//      //glColor4f(1,1,1,.7);
//      glColor4f(.3,.3,1,.7);
//      for (size_t i = 0; i < crease->mFaces.size(); ++i)
//      {
//         int fi = crease->mFaces[i];
//         Face& f = mMesh.crease_faces[fi];
//         for (int v = 0; v<3; ++v)
//            gl::Vertex(mMesh.verts[f.vertex[v]]);
//      }
//      glEnd();
//      glEnable(GL_CULL_FACE);
//   }
//   ViewScene::GetInstance().LoadProjection(1/1.001f);
//   glColor3f(.3,1,.3);
//   glLineWidth(3);
//   for (size_t i = 0; i < crease->mLoops.size(); ++i)
//   {
//      VertexLoop* loop = crease->mLoops[i];
//      glBegin(GL_LINE_LOOP);
//      for (size_t v = 0; v < loop->mVertices.size(); ++v)
//      {
//         Vec3& vert = mMesh.verts[loop->mVertices[v]];
//         gl::Vertex(vert);         
//      }
//      glEnd();
//   }
//   glLineWidth(1);
//   
//   ViewScene::GetInstance().LoadProjection(1.0f);
//}

void MeshView::DrawSelFaces()
{
   if (mSelectedFaces.empty()) return;
   static const float texCoords[3][2] = { { 0,0 }, { 6, 0}, {0, 6} };
   gl::NoLighting state1;
   {
      gl::Blend state2;
      ViewScene::GetInstance().LoadProjection(1/1.05f);
      SelectTexture::Bind();
      glDisable(GL_CULL_FACE);
      glBegin(GL_TRIANGLES);
      glColor4f(1,1,1,.7f);
      
      //glColor4f(0,.7f,1.0f,.3f);
      for (size_t i = 0; i < mSelectedFaces.size(); ++i)
      {
         int fi = mSelectedFaces[i];
         Face& f = mMesh.crease_faces[fi];
         for (int v = 0; v < 3; ++v)
         {
            glTexCoord2f(texCoords[v][0], texCoords[v][1]);
            gl::Vertex(mMesh.verts[f.vertex[v]]);
         }
      }
      glEnd();
      SelectTexture::Unbind();
      glEnable(GL_CULL_FACE);

      ViewScene::GetInstance().LoadProjection(1/1.001f);
      glColor3f(.3,1,.3);
      glLineWidth(3);
      glBegin(GL_LINES);
         for (size_t i = 0; i < mSelectedFacesBorder.size(); ++i)
         {
            Edge& e = mSelectedFacesBorder[i];
            gl::Vertex(mMesh.verts[e.first]);
            gl::Vertex(mMesh.verts[e.second]);
         }
      glEnd();
      glLineWidth(1);
      
      ViewScene::GetInstance().LoadProjection(1.0f);
   }
   ViewScene::GetInstance().LoadProjection(1.0f);
}


void MeshView::DrawSelEdges()
{
   if (mSelectedEdges.empty()) return;
   gl::NoLighting state1;
   {
      gl::Blend state2;
      ViewScene::GetInstance().LoadProjection(1/1.005f);
      glColor3f(.3,1,.3);
      glLineWidth(3);
      glBegin(GL_LINES);
      for (size_t i = 0; i < mSelectedEdges.size(); ++i)
      {
         Edge e = mSelectedEdges[i];
         gl::Vertex(mMesh.verts[e.first]);
         gl::Vertex(mMesh.verts[e.second]);
      }
      glEnd();
      glLineWidth(1);
   }
   ViewScene::GetInstance().LoadProjection(1.0f);
}


void MeshView::MoveSelectedVerts(Vec3 offset)
{
   //std::vector<int> selVerts;
   //GetSelectedVertices(selVerts);
   for (size_t i = 0; i < mSelectedVerts.size(); ++i)
   {
      size_t vi = mSelectedVerts[i];
      Vec3& v = mMesh.verts[vi];
      v += offset;
   }
   mFaceMeshDraw.SetMesh(mFaceMesh);
}

void MeshView::RebuildBase()
{
   mFaceMeshDraw.SetMesh(mFaceMesh);
}

void MeshView::Rebuild()
{
   UpdateMesh(); //mFaceUpdating = true; mPolyUpdating = true; 
   if (mSubdividedMesh) {// mSubdividedMesh->Rebuild();
      mSubdividedMesh->Rebuild();
      int level = mSubdivisionLevel;
      SetSubdivision(0);
      SetSubdivision(level);
   }

   ClearSelection();
}
void MeshView::ClearSelection()
{
   mSelectedVerts.clear();
   mSelectedLoops.clear();
   mSelectedFaces.clear();
   mSelectedFacesBorder.clear();
}

void MeshView::GetSelectedFaces(std::vector<int>& aFaces)
{
   //if (ViewScene::GetInstance().GetSelectionMode() == ViewScene::cFACE)
   //{
   //   aFaces = mSelectedFaces;
   //}
   //else if (ViewScene::GetInstance().GetSelectionMode() == ViewScene::cVERTEX)
   //{
   //   MeshAlgorithm::FindFaces(*mMesh.crease_faces, GetSelectedVertices(), aFaces);
   //}
   aFaces = mSelectedFaces;
}
void MeshView::GetSelectedVerts(std::vector<int>& aVerts)
{
   aVerts = mSelectedVerts;
   //if (ViewScene::GetInstance().GetSelectionMode() == ViewScene::cFACE)
   //{
   //   for (size_t i = 0; i < mSelectedFaces.size(); ++i)
   //   {
   //      int fi = mSelectedFaces[i];
   //      Face& f= mMesh.crease_faces[fi];
   //      for (int j = 0; j < 3; ++j) aVerts.push_back(f.vertex[j]);
   //   }
   //   std::sort(aVerts.begin(), aVerts.end());
   //   aVerts.erase(std::unique(aVerts.begin(), aVerts.end()), aVerts.end());
   //}
   //else if (ViewScene::GetInstance().GetSelectionMode() == ViewScene::cVERTEX)
   //{
   //   aVerts = mSelectedVerts;
   //}
}

CreaseStructure& MeshView::GetCreases()
{
   if (! mCreasesUpdated)
   {
      if (OptionSet(cKEEP_CREASE_STRUCTURE))
      {
         MeshAdjacency adj(mMesh.GetCreaseMesh());
         mCreases.Build(*mMesh.crease_faces);
         mCreasesUpdated = true;
      }
   }
   return mCreases;
}
MeshAdjacency& MeshView::GetMeshAdjacency()
{
   if (!mMeshAdjacencyValid)
   {
      mAdjacency.Rebuild(mMesh.GetCreaseMesh());
      mMeshAdjacencyValid = true;
   }
   return mAdjacency;
}

void MeshView::SetSelectedFaces(IndexList& aFaces)
{
   mSelectedFaces.swap(aFaces);
   mSelectedFacesBorder.clear();
   std::set<Edge> borderEdges;
   for (size_t i = 0; i < mSelectedFaces.size(); ++i)
   {
      int fi = mSelectedFaces[i];
      Face& f = mMesh.crease_faces[fi];
      Edge edges[] = { OrderEdge(f.vertex[0], f.vertex[1]),
         OrderEdge(f.vertex[1], f.vertex[2]),
         OrderEdge(f.vertex[2], f.vertex[0]) };
      for (int ei = 0; ei < 3; ++ei)
      {
         std::set<Edge>::iterator iter = borderEdges.find(edges[ei]);
         if (iter == borderEdges.end())
         {
            borderEdges.insert(edges[ei]);
         }
         else
         {
            borderEdges.erase(iter);
         }
      }
   }
   mSelectedFacesBorder.assign(borderEdges.begin(), borderEdges.end());
   SelectionUpdated();
}
